#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <ctype.h>
#include <termios.h>

// RK Vendor Storage IOCTL definitions
#define VENDOR_REQ_TAG      0x56524551
#define VENDOR_READ_IO      _IOW('v', 0x01, unsigned int)
#define VENDOR_WRITE_IO     _IOW('v', 0x02, unsigned int)  // 修正：写入使用0x02

// Vendor storage request structure (与demo保持一致)
struct rk_vendor_req {
    uint32_t tag;       // Must be VENDOR_REQ_TAG
    uint16_t id;        // Vendor storage ID
    uint16_t len;       // Data length
    uint8_t data[1];    // Flexible array member (实际大小由外部缓冲区决定)
};

// Device configuration structure
struct device_config {
    char device_type[16];
    char sn[32];
    char cmei[32];
    char device_key[128];
};

// Vendor storage ID definitions - 使用安全的自定义ID范围
#define VENDOR_ID_SN        16  // Custom: Serial Number (避免系统预定义ID 1-4)
#define VENDOR_ID_DEVICE_TYPE   17  // Custom: Device Type
#define VENDOR_ID_CMEI      18  // Custom: CMEI
#define VENDOR_ID_DEVICE_KEY    19  // Custom: Device Key

#define DEVICE_PATH "/dev/vendor_storage"

// Terminal control functions
void clear_screen(void)
{
    printf("\033[2J\033[H");
    fflush(stdout);
}

void set_cursor_position(int row, int col)
{
    printf("\033[%d;%dH", row, col);
    fflush(stdout);
}

void set_color(int color)
{
    printf("\033[%dm", color);
    fflush(stdout);
}

void reset_color(void)
{
    printf("\033[0m");
    fflush(stdout);
}

// Colors
#define COLOR_RESET     0
#define COLOR_RED       31
#define COLOR_GREEN     32
#define COLOR_YELLOW    33
#define COLOR_BLUE      34
#define COLOR_MAGENTA   35
#define COLOR_CYAN      36
#define COLOR_WHITE     37

// Function to get user input with validation
int get_user_input(const char *prompt, char *buffer, int max_len, int (*validator)(const char *))
{
    char input[256];
    
    while (1) {
        printf("%s", prompt);
        fflush(stdout);
        
        if (fgets(input, sizeof(input), stdin) == NULL) {
            return -1;
        }
        
        // Remove newline
        input[strcspn(input, "\n")] = '\0';
        
        // Check length
        if (strlen(input) >= max_len) {
            set_color(COLOR_RED);
            printf("错误：输入长度超过限制 (%d 字符)\n", max_len - 1);
            reset_color();
            continue;
        }
        
        // Validate input
        if (validator && !validator(input)) {
            continue;
        }
        
        strcpy(buffer, input);
        return 0;
    }
}

// Validators
int validate_device_type(const char *input)
{
    if (strlen(input) == 0) {
        set_color(COLOR_RED);
        printf("错误：设备类型不能为空\n");
        reset_color();
        return 0;
    }
    
    // Check if all characters are digits
    for (int i = 0; input[i]; i++) {
        if (!isdigit(input[i])) {
            set_color(COLOR_RED);
            printf("错误：设备类型只能包含数字\n");
            reset_color();
            return 0;
        }
    }
    
    return 1;
}

int validate_sn(const char *input)
{
    if (strlen(input) == 0) {
        set_color(COLOR_RED);
        printf("错误：序列号不能为空\n");
        reset_color();
        return 0;
    }
    
    if (strlen(input) < 10) {
        set_color(COLOR_RED);
        printf("错误：序列号长度至少10位\n");
        reset_color();
        return 0;
    }
    
    return 1;
}

int validate_cmei(const char *input)
{
    if (strlen(input) == 0) {
        set_color(COLOR_RED);
        printf("错误：CMEI不能为空\n");
        reset_color();
        return 0;
    }
    
    if (strlen(input) < 10) {
        set_color(COLOR_RED);
        printf("错误：CMEI长度至少10位\n");
        reset_color();
        return 0;
    }
    
    return 1;
}

int validate_device_key(const char *input)
{
    if (strlen(input) == 0) {
        set_color(COLOR_RED);
        printf("错误：设备密钥不能为空\n");
        reset_color();
        return 0;
    }
    
    if (strlen(input) < 32) {
        set_color(COLOR_RED);
        printf("错误：设备密钥长度至少32位\n");
        reset_color();
        return 0;
    }
    
    // Check if all characters are hex digits
    for (int i = 0; input[i]; i++) {
        if (!isxdigit(input[i])) {
            set_color(COLOR_RED);
            printf("错误：设备密钥只能包含十六进制字符 (0-9, A-F)\n");
            reset_color();
            return 0;
        }
    }
    
    return 1;
}

// Vendor storage operations (same as before)
int vendor_storage_write(int fd, uint16_t id, const void *data, uint16_t len)
{
    uint8_t p_buf[2048];  // 使用与demo相同的缓冲区大小
    struct rk_vendor_req *req;
    int ret;
    
    req = (struct rk_vendor_req *)p_buf;
    memset(req, 0, sizeof(p_buf));
    
    req->tag = VENDOR_REQ_TAG;
    req->id = id;
    req->len = len;
    
    if (len > (sizeof(p_buf) - sizeof(struct rk_vendor_req) + 1)) {
        fprintf(stderr, "错误：数据长度 %d 超过最大值\n", len);
        return -1;
    }
    
    memcpy(req->data, data, len);
    
    ret = ioctl(fd, VENDOR_WRITE_IO, req);
    if (ret < 0) {
        fprintf(stderr, "错误：写入vendor storage ID %d 失败: %s\n", id, strerror(errno));
        return ret;
    }
    
    return 0;
}

int vendor_storage_read(int fd, uint16_t id, void *data, uint16_t len)
{
    uint8_t p_buf[2048];  // 使用与demo相同的缓冲区大小
    struct rk_vendor_req *req;
    int ret;
    
    req = (struct rk_vendor_req *)p_buf;
    memset(req, 0, sizeof(p_buf));
    
    req->tag = VENDOR_REQ_TAG;
    req->id = id;
    req->len = 512;  // 使用与demo相同的最大读取长度
    
    ret = ioctl(fd, VENDOR_READ_IO, req);
    if (ret < 0) {
        fprintf(stderr, "错误：读取vendor storage ID %d 失败: %s\n", id, strerror(errno));
        return ret;
    }
    
    // req->len 现在包含实际读取的数据长度
    if (req->len > len) {
        req->len = len;
    }
    
    memcpy(data, req->data, req->len);
    return req->len;
}

// Write device configuration to vendor storage
int write_device_config(int fd, struct device_config *config)
{
    int ret = 0;
    
    set_color(COLOR_YELLOW);
    printf("正在写入设备配置到vendor storage...\n");
    reset_color();
    
    // Write Serial Number (ID 20) - 避免覆盖系统预定义SN
    ret = vendor_storage_write(fd, VENDOR_ID_SN, config->sn, strlen(config->sn));
    if (ret != 0) return ret;
    printf("✓ SN写入成功\n");
    
    // Write Device Type (ID 16)
    ret = vendor_storage_write(fd, VENDOR_ID_DEVICE_TYPE, config->device_type, strlen(config->device_type));
    if (ret != 0) return ret;
    printf("✓ 设备类型写入成功\n");
    
    // Write CMEI (ID 17)
    ret = vendor_storage_write(fd, VENDOR_ID_CMEI, config->cmei, strlen(config->cmei));
    if (ret != 0) return ret;
    printf("✓ CMEI写入成功\n");
    
    // Write Device Key (ID 18)
    ret = vendor_storage_write(fd, VENDOR_ID_DEVICE_KEY, config->device_key, strlen(config->device_key));
    if (ret != 0) return ret;
    printf("✓ 设备密钥写入成功\n");
    
    set_color(COLOR_GREEN);
    printf("所有设备配置写入成功！\n");
    reset_color();
    return 0;
}

// Read device configuration from vendor storage
int read_device_config(int fd, struct device_config *config)
{
    int ret;
    
    set_color(COLOR_YELLOW);
    printf("正在从vendor storage读取设备配置...\n");
    reset_color();
    
    memset(config, 0, sizeof(*config));
    
    // Read Serial Number (ID 20) - 从自定义位置读取
    ret = vendor_storage_read(fd, VENDOR_ID_SN, config->sn, sizeof(config->sn) - 1);
    if (ret < 0) {
        set_color(COLOR_RED);
        printf("警告：无法读取SN，可能未设置\n");
        reset_color();
        strcpy(config->sn, "未设置");
    } else {
        config->sn[ret] = '\0';  // Ensure null termination
        printf("✓ SN读取成功: %s\n", config->sn);
    }
    
    // Read Device Type (ID 16)
    ret = vendor_storage_read(fd, VENDOR_ID_DEVICE_TYPE, config->device_type, sizeof(config->device_type) - 1);
    if (ret < 0) return ret;
    printf("✓ 设备类型读取成功\n");
    
    // Read CMEI (ID 17)
    ret = vendor_storage_read(fd, VENDOR_ID_CMEI, config->cmei, sizeof(config->cmei) - 1);
    if (ret < 0) return ret;
    printf("✓ CMEI读取成功\n");
    
    // Read Device Key (ID 18)
    ret = vendor_storage_read(fd, VENDOR_ID_DEVICE_KEY, config->device_key, sizeof(config->device_key) - 1);
    if (ret < 0) return ret;
    printf("✓ 设备密钥读取成功\n");
    
    set_color(COLOR_GREEN);
    printf("所有设备配置读取成功！\n");
    reset_color();
    return 0;
}

// Display configuration
void display_config(struct device_config *config)
{
    set_color(COLOR_CYAN);
    printf("\n╔══════════════════════════════════════════════════════════════════════════════╗\n");
    printf("║                                设备配置信息                                  ║\n");
    printf("╠══════════════════════════════════════════════════════════════════════════════╣\n");
    reset_color();
    
    printf("║ 设备类型: %-66s ║\n", config->device_type);
    printf("║ 序列号:   %-66s ║\n", config->sn);
    printf("║ CMEI:     %-66s ║\n", config->cmei);
    printf("║ 设备密钥: %-66s ║\n", config->device_key);
    
    set_color(COLOR_CYAN);
    printf("╚══════════════════════════════════════════════════════════════════════════════╝\n");
    reset_color();
}

// Main menu
void show_main_menu(void)
{
    clear_screen();
    
    set_color(COLOR_BLUE);
    printf("╔══════════════════════════════════════════════════════════════════════════════╗\n");
    printf("║                        RK Vendor Storage 配置工具                           ║\n");
    printf("║                           作者: Zhang Zhen                                  ║\n");
    printf("║                    邮箱: zhangzhen@cmhi.chinamobile.com                     ║\n");
    printf("╚══════════════════════════════════════════════════════════════════════════════╝\n");
    reset_color();
    
    printf("\n");
    set_color(COLOR_GREEN);
    printf("请选择操作:\n");
    reset_color();
    printf("  1. 配置并写入设备信息\n");
    printf("  2. 从vendor storage读取配置\n");
    printf("  0. 退出\n");
    printf("\n");
}

// Input device configuration
int input_device_config(struct device_config *config)
{
    clear_screen();
    
    set_color(COLOR_BLUE);
    printf("╔══════════════════════════════════════════════════════════════════════════════╗\n");
    printf("║                              输入设备配置                                   ║\n");
    printf("╚══════════════════════════════════════════════════════════════════════════════╝\n");
    reset_color();
    
    printf("\n");
    
    // Input Device Type
    if (get_user_input("请输入设备类型 (示例: 591844): ", config->device_type, sizeof(config->device_type), validate_device_type) != 0) {
        return -1;
    }
    
    // Input SN
    if (get_user_input("请输入序列号 (示例: 1222002029188671270000006): ", config->sn, sizeof(config->sn), validate_sn) != 0) {
        return -1;
    }
    
    // Input CMEI
    if (get_user_input("请输入CMEI (示例: 188671270000006): ", config->cmei, sizeof(config->cmei), validate_cmei) != 0) {
        return -1;
    }
    
    // Input Device Key
    if (get_user_input("请输入设备密钥 (示例: 00010001C7C885685B2D5BBCF007F7AADCD878F183652C9DAA4654851FB281CCDE065024): ", config->device_key, sizeof(config->device_key), validate_device_key) != 0) {
        return -1;
    }
    
    set_color(COLOR_GREEN);
    printf("\n设备配置输入完成！\n");
    reset_color();
    
    return 0;
}

// Wait for user input
void wait_for_enter(void)
{
    printf("\n按回车键继续...");
    fflush(stdout);
    getchar();
}

int main(void)
{
    struct device_config config;
    int choice;
    int fd;
    int config_loaded = 0;
    
    // Initialize config
    memset(&config, 0, sizeof(config));
    
    while (1) {
        show_main_menu();
        
        printf("请输入选择 (0-2): ");
        fflush(stdout);
        
        if (scanf("%d", &choice) != 1) {
            // Clear input buffer
            int c;
            while ((c = getchar()) != '\n' && c != EOF);
            
            set_color(COLOR_RED);
            printf("错误：请输入有效的数字选择\n");
            reset_color();
            wait_for_enter();
            continue;
        }
        
        // Clear input buffer
        int c;
        while ((c = getchar()) != '\n' && c != EOF);
        
        switch (choice) {
            case 1: // Configure and write device information
                // Step 1: Input configuration
                if (input_device_config(&config) == 0) {
                    config_loaded = 1;
                    
                    // Step 2: Display configuration
                    printf("\n");
                    set_color(COLOR_CYAN);
                    printf("═══════════════════════════════════════════════════════════════════════════════\n");
                    printf("                              配置预览                                        \n");
                    printf("═══════════════════════════════════════════════════════════════════════════════\n");
                    reset_color();
                    display_config(&config);
                    
                    // Step 3: Confirm and write
                    printf("\n");
                    set_color(COLOR_YELLOW);
                    printf("确认写入到vendor storage? (y/N): ");
                    reset_color();
                    fflush(stdout);
                    
                    char confirm;
                    if (scanf("%c", &confirm) == 1 && (confirm == 'y' || confirm == 'Y')) {
                        // Open vendor storage device
                        fd = open(DEVICE_PATH, O_RDWR);
                        if (fd < 0) {
                            set_color(COLOR_RED);
                            printf("错误：无法打开 %s: %s\n", DEVICE_PATH, strerror(errno));
                            printf("请确保您有root权限且设备存在\n");
                            reset_color();
                        } else {
                            write_device_config(fd, &config);
                            close(fd);
                        }
                    } else {
                        set_color(COLOR_YELLOW);
                        printf("操作已取消\n");
                        reset_color();
                    }
                    
                    // Clear input buffer
                    while ((c = getchar()) != '\n' && c != EOF);
                }
                wait_for_enter();
                break;
                
            case 2: // Read configuration from vendor storage
                // Open vendor storage device
                fd = open(DEVICE_PATH, O_RDWR);
                if (fd < 0) {
                    set_color(COLOR_RED);
                    printf("错误：无法打开 %s: %s\n", DEVICE_PATH, strerror(errno));
                    printf("请确保您有root权限且设备存在\n");
                    reset_color();
                } else {
                    if (read_device_config(fd, &config) == 0) {
                        config_loaded = 1;
                        display_config(&config);
                    }
                    close(fd);
                }
                wait_for_enter();
                break;
                
            case 0: // Exit
                clear_screen();
                set_color(COLOR_GREEN);
                printf("感谢使用RK Vendor Storage配置工具！\n");
                reset_color();
                return 0;
                
            default:
                set_color(COLOR_RED);
                printf("错误：无效的选择，请输入0-5之间的数字\n");
                reset_color();
                wait_for_enter();
                break;
        }
    }
    
    return 0;
}
